AWS Resource Access Manager (RAM) の共有先を SCP で制限する

AWS Resource Access Manager (RAM) の共有先を SCP で制限する

Clock Icon2025.01.13

いわさです。

先日、AWS Transit Gateway を組織内で共有した時に、SCP を使ってアタッチメント作成を行えないようにしてみました。

https://dev.classmethod.jp/articles/scp-tgw-ram-ou-deny/

組織内共有されている Transit Gateway に対して、指定した OU から誤ってアタッチメント作成してしまうことを制限出来ると思います。
一方で Transit Gateway に限らず、そもそも組織内共有の共有先をもう少し制限出来ないものかと思ったりもします。

今回は前回の延長で、RAM で共有を行う際に SCP で共有先を制限出来ないか試してみたいと思います。

前提の確認

前回の記事でも触れられていますが、RAM でリソース共有を作成するとCreateResourceShareアクションが実行されます。
今回はリソース共有作成を制限したいので、このアクションを SCP で制限してみたいと思います。

https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/list_awsresourceaccessmanagerram.html

上記からCreateResourceShareアクションで利用できる条件キーは以下のあたりです。

  • aws:RequestTag/${TagKey}
  • aws:TagKeys
  • ram:RequestedResourceType
  • ram:ResourceArn
  • ram:RequestedAllowsExternalPrincipals
  • ram:Principal

ram:RequestedResourceTyperam:ResourceArnはリソース共有作成時に指定するリソースに関してですね。

7B8782EF-1236-40A8-B220-CA50EDECD906.png

例えば「RAM の組織共有は有効化したいけども特定のリソースタイプのみに限りたい」という設定をしたい時に使えそうです。

そして、ram:RequestedAllowsExternalPrincipalsram:Principalは共有先に関する条件に使えそうです。
ということで今回は上記2つのキーに関して評価して、SCP で使ってみます。

外部との共有を制限する

まずはram:RequestedAllowsExternalPrincipalsです。
こちらは非常にイメージしやすいのですが、リソース共有作成時の以下設定値に関するものになります。

887CF9DB-2DC3-4126-B92E-BEC02ED0A598.png

「すべてのユーザーとの共有を許可」では組織外の AWS アカウント ID などを指定して共有が可能です。
「自分の組織内でのみ共有を許可」では組織外の AWS アカウント ID などの指定ができなくなります。

組織内共有は OK だけど、組織外との共有を制限したいということはよくありそうです。ram:RequestedAllowsExternalPrincipalsで制限してみましょう。
次のような SCP を作成して OU にアタッチしました。

3BE4C56B-B6F2-4B51-AE11-52369B4E58D4.png

「すべてのユーザーとの共有を許可」を「はい」にするとリソース共有の作成に失敗するようになりました。

CEFE0288-1AFF-4ADC-9161-BD7C12260395.png

「自分の組織内でのみ共有を許可」の場合は成功します。

BA05173B-6EE3-46A5-847C-55AF05B8F132.png

ただし、「すべてのユーザーとの共有を許可」を「はい」にすると組織内の AWS アカウントや OU を指定した場合でもエラーになります。
この条件キーは「外部プリンシパルを許可」の値のみがチェック対象ですので注意しましょう。

CAED9F25-5042-48E1-A9AC-DE1EA9AB866A.png

プリンシパルを制限する

組織外共有の制限が出来そうだということで、続いては組織内の共有先制限も出来るか見てみましょう。
今度はram:Principalが使えそうです。

ただし、厄介なことにこの共有先として指定するプリンシパルは色々なタイプがあります。

83E4E951-9319-4B9A-8492-466E9033B4CB_1_105_c.jpeg

当然ですがそれぞれのプリンシパルタイプに対してそもそも許可するのかしないのかの要件を事前に整理しておく必要があります。
どのプリンシパルタイプでも ARN、AWS アカウント ID、サービスプリンシパルの文字列をram:Principalでフィルタリングする形になります。

参考までにそれぞれのプリンシパルタイプを指定した時の CloudTrail イベントレコードの情報を調べたので記載しておきます。

アカウントを指定した場合

    "requestParameters": {
        "name": "hoge0113share2ouc",
        "resourceArns": [],
        "principals": [
            "111122223333"
        ],
        "permissionArns": [],
        "allowExternalPrincipals": false,
        "tags": []
    },

組織 ID を指定した場合

    "requestParameters": {
        "name": "hoge0113share2",
        "resourceArns": [],
        "principals": [
            "arn:aws:organizations::123456789012:organization/o-8j81brsjuj"
        ],
        "permissionArns": [],
        "allowExternalPrincipals": false,
        "tags": []
    },

任意の OU A を指定した場合

    "requestParameters": {
        "name": "hoge0113ouc",
        "resourceArns": [],
        "principals": [
            "arn:aws:organizations::123456789012:ou/o-8j81brsjuj/ou-s4h9-o3k5ritj"
        ],
        "permissionArns": [],
        "allowExternalPrincipals": false,
        "tags": []
    },

OU-A の子 OU である、OU B を指定した場合

    "requestParameters": {
        "name": "hoge0113child",
        "resourceArns": [],
        "principals": [
            "arn:aws:organizations::123456789012:ou/o-8j81brsjuj/ou-s4h9-i8dknce4"
        ],
        "permissionArns": [],
        "allowExternalPrincipals": false,
        "tags": []
    },

IAM ユーザーを指定した場合

    "requestParameters": {
        "name": "hoge0113shareservice",
        "resourceArns": [],
        "principals": [
            "arn:aws:iam::123456789012:user/hoge"
        ],
        "permissionArns": [],
        "allowExternalPrincipals": false,
        "tags": []
    },

試しに特定 OU を拒否してみますか。次のような SCP を作成してアタッチしました。

EA32A79C-B5A8-489F-B968-275DC995A471.png

良いですね。指定した OU に対するリソース共有を作成しようとしたところエラーとなりました。

107FF0EB-7899-4459-AFE3-778D279B1488.png

一方で、OU の ARN は階層構造になっているわけではないので禁止された OU の下層にある OU であれば許可出来たりします。

836E43C9-2E7A-4B27-B4F8-19844A51909A.png

あとはアカウント ID や組織 ID の指定も可能です。そうなってくるとブラックリスト形式での指定は非常に大変そうです。
特定の OU のみ許可するような、次のようなホワイトリスト形式のほうが良さそうかなという感じがします。

BAD046A2-AA26-4C62-8288-D06129DCB755.png

まとめたポリシーを作成する

さらにまだいくつか考慮しなければいけないこともあります。
リソース共有は変更が可能です。外部共有の ON/OFF 設定を変更したり、共有先プリンシパルの追加が可能です。

この時どうなるかというと、リソース共有に対して共有プリンシパルを追加したり、あるいは対象リソースを追加する時にはram:AssociateResourceShareが発生します。
リソース共有は共有プリンシパルやリソースの指定はせずにとりあえず作成だけして、後から共有プリンシパルやリソースを追加する使い方をするのが多いです。なのでram:AssociateResourceShareアクションは無視できません。
ただ、調べたところram:AssociateResourceShareram:Principal条件キーは使用可能です。やったね。

また、外部共有の ON/OFF 変更など、リソースやプリンシパルの追加以外のリソース共有自体の設定変更についてはram:UpdateResourceShareが発生しました。
こちらもram:RequestedAllowsExternalPrincipals条件キーが使用可能です。

以上をまとめるとこんな感じになると思います。
SCP はアタッチ出来る上限数があるので[1]、ひとつにまとめてみます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Statement1",
      "Effect": "Deny",
      "Action": [
        "ram:CreateResourceShare",
        "ram:AssociateResourceShare"
      ],
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "ram:Principal": [
            "arn:aws:organizations::123456789012:ou/o-8j81brsjuj/ou-s4h9-i056l45b",
            "arn:aws:organizations::123456789012:ou/o-8j81brsjuj/ou-s4h9-ofgjiapb"
          ]
        },
        "Null": {
          "ram:Principal": false
        }
      }
    },
    {
      "Sid": "Statement2",
      "Effect": "Deny",
      "Action": [
        "ram:CreateResourceShare",
        "ram:UpdateResourceShare"
      ],
      "Resource": "*",
      "Condition": {
        "Bool": {
          "ram:RequestedAllowsExternalPrincipals": "true"
        }
      }
    }
  ]
}

ram:CreateResourceShareはリソース共有作成時にプリンシパルを指定しない場合があったり、ram:AssociateResourceShareではプリンシパルではなくリソースイベントが入ってくることがあります。
そのため指定しなかった場合に Deny が起きないように Null 条件を指定しています。[2]

動作確認してみましょう。
まずプリンシパルやリソースを指定せずに内部共有可能なリソース共有を作成することができました。

ABA37281-E0E6-4628-8ADA-937D9B460A34.png

これを外部共有可能に設定しようとするとエラーが発生しました。

409BE95A-A5A0-48D4-BEB4-F8DF2D10CEC4.png

さらに、許可されていない OU をプリンシパルに指定しようとするとエラーになりました。

69240A82-4319-448D-9B27-F368CBEEC20F.png

そして、許可されている OU であればプリンシパルへの追加ができました。

06457399-2275-4BF9-9BF0-2BB33A87BBFC.png

期待どおり動作していそうですね。

さいごに

本日はAWS Resource Access Manager (RAM) の共有先を SCP で制限してみました。

なかなか良いのではないでしょうか。
デフォルトだと RAM の組織利用が有効化されると、結構オープンに共有可能になってしまうので SCP によるリソース共有の制限は使えそうです。

脚注
  1. AWS Organizations の サービスコントロールポリシー (SCP) を用いて、複数アカウントにリージョン利用制限するパターンをまとめてみた | DevelopersIO ↩︎

  2. 【AWS IAM】Condition の条件キーやポリシー変数は可用性を意識しよう!という話 | DevelopersIO ↩︎

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.